package com.et114.core.utility;

/*
 * @author guanhw
 */
public class Native2Ascii {
	private static final String specialSaveChars = "=: \t\r\n\f#!";

	public static String decode( String theString ) {
		char aChar;
		int len = theString.length();
		StringBuffer outBuffer = new StringBuffer( len );

		for ( int x = 0; x < len; ) {
			aChar = theString.charAt( x++ );
			if ( aChar == '|' ) {
				aChar = theString.charAt( x++ );
				if ( aChar == 'u' ) {
					// Read the xxxx
					int value = 0;
					for ( int i = 0; i < 4; i++ ) {
						aChar = theString.charAt( x++ );
						if(aChar>='0'&&aChar<='9'){
							value = ( value << 4 ) + aChar - '0';
						}else if(aChar>='a'&&aChar<='f'){
							value = ( value << 4 ) + 10 + aChar - 'a';
						}else if(aChar>='A'&&aChar<='F'){
							value = ( value << 4 ) + 10 + aChar - 'A';
						}else{
							throw new IllegalArgumentException("Malformed \\uxxxx encoding." );
						}
					}
					outBuffer.append( ( char ) value );
				}
				else {
					outBuffer.append( "|" );
					x--;
				}
			}
			else if ( aChar == '\\' ) {
				aChar = theString.charAt( x++ );
				if ( aChar == 't' ) {
					aChar = '\t';
				}
				else if ( aChar == 'r' ) {
					aChar = '\r';
				}
				else if ( aChar == 'n' ) {
					aChar = '\n';
				}
				else if ( aChar == 'f' ) {
					aChar = '\f';
				}
				outBuffer.append( aChar );
			}
			else {
				outBuffer.append( aChar );
			}
		}
		String s = outBuffer.toString();
		return s;
	}

	public static String encode( String theString ) {
		int len = theString.length();
		StringBuffer outBuffer = new StringBuffer( len * 2 );

		for ( int x = 0; x < len; x++ ) {
			char aChar = theString.charAt( x );
			switch ( aChar ) {
				case ' ':
					if ( x == 0 ) {
						outBuffer.append( '\\' );
					}
					outBuffer.append( ' ' );
					break;
				case '\\':
					outBuffer.append( '\\' );
					outBuffer.append( '\\' );
					break;
				case '\t':
					outBuffer.append( '\\' );
					outBuffer.append( 't' );
					break;
				case '\n':
					outBuffer.append( '\\' );
					outBuffer.append( 'n' );
					break;
				case '\r':
					outBuffer.append( '\\' );
					outBuffer.append( 'r' );
					break;
				case '\f':
					outBuffer.append( '\\' );
					outBuffer.append( 'f' );
					break;
				default:
					if ( ( aChar < 0x0020 ) || ( aChar > 0x007e ) ) {
						outBuffer.append( '\\' );
						outBuffer.append( 'u' );
						outBuffer.append( toHex( ( aChar >> 12 ) & 0xF ) );
						outBuffer.append( toHex( ( aChar >> 8 ) & 0xF ) );
						outBuffer.append( toHex( ( aChar >> 4 ) & 0xF ) );
						outBuffer.append( toHex( aChar & 0xF ) );
					}
					else {
						if ( specialSaveChars.indexOf( aChar ) != -1 ) {
							outBuffer.append( '\\' );
						}
						outBuffer.append( aChar );
					}
			}
		}
		return outBuffer.toString();
	}

	/**
	 * Convert a nibble to a hex character
	 * @param	nibble	the nibble to convert.
	 */
	private static char toHex( int nibble ) {
		return hexDigit[ ( nibble & 0xF )];
	}

	/** A table of hex digits */
	private static final char[] hexDigit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

	public static void main( String[] a ) {
		System.out.println( Native2Ascii.encode( "ddddd\\\\\\\\ " ) );
		System.out.println( Native2Ascii.decode( "ddddd\\\\\\\\  " ) );
	}

}
